home *** CD-ROM | disk | FTP | other *** search
- /*
- * jcmain.c
- *
- * Copyright (C) 1991, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
- *
- * This file contains a trivial test user interface for the JPEG compressor.
- * It should work on any system with Unix- or MS-DOS-style command lines.
- *
- * Two different command line styles are permitted, depending on the
- * compile-time switch TWO_FILE_COMMANDLINE:
- * cjpeg [options] inputfile outputfile
- * cjpeg [options] [inputfile]
- * In the second style, output is always to standard output, which you'd
- * normally redirect to a file or pipe to some other program. Input is
- * either from a named file or from standard input (typically redirected).
- * The second style is convenient on Unix but is unhelpful on systems that
- * don't support pipes. Also, you MUST use the first style if your system
- * doesn't do binary I/O to stdin/stdout.
- */
-
- #include "jinclude.h"
- #ifdef __STDC__
- #include <stdlib.h> /* to declare exit() */
- #endif
-
- #ifdef THINK_C
- #include <console.h> /* command-line reader for Macintosh */
- #endif
-
- #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
- #define READ_BINARY "r"
- #define WRITE_BINARY "w"
- #else
- #define READ_BINARY "rb"
- #define WRITE_BINARY "wb"
- #endif
-
-
- /*
- * If your system has getopt(3), you can use your library version by
- * defining HAVE_GETOPT. By default, we use the PD 'egetopt'.
- */
-
- #ifdef HAVE_GETOPT
- extern int getopt PP((int argc, char **argv, char *optstring));
- extern char * optarg;
- extern int optind;
- #else
- #include "egetopt.c"
- #define getopt(argc,argv,opt) egetopt(argc,argv,opt)
- #endif
-
-
- /*
- * This routine determines what format the input file is,
- * and selects the appropriate input-reading module.
- *
- * To determine which family of input formats the file belongs to,
- * we look only at the first byte of the file, since C does not
- * guarantee that more than one character can be pushed back with ungetc.
- * This is sufficient for the currently envisioned set of input formats.
- *
- * If you need to look at more than one character to select an input module,
- * you can either
- * 1) assume you can fseek() the input file (may fail for piped input);
- * 2) assume you can push back more than one character (works in
- * some C implementations, but unportable);
- * or 3) don't put back the data, and modify the various input_init
- * methods to assume they start reading after the start of file.
- */
-
- LOCAL void
- select_file_type (compress_info_ptr cinfo)
- {
- int c;
-
- if ((c = getc(cinfo->input_file)) == EOF)
- ERREXIT(cinfo->emethods, "Empty input file");
-
- switch (c) {
- #ifdef GIF_SUPPORTED
- case 'G':
- jselrgif(cinfo);
- break;
- #endif
- #ifdef PPM_SUPPORTED
- case 'P':
- jselrppm(cinfo);
- break;
- #endif
- default:
- ERREXIT(cinfo->emethods, "Unsupported input file format");
- break;
- }
-
- if (ungetc(c, cinfo->input_file) == EOF)
- ERREXIT(cinfo->emethods, "ungetc failed");
- }
-
-
- /*
- * This routine gets control after the input file header has been read.
- * It must determine what output JPEG file format is to be written,
- * and make any other compression parameter changes that are desirable.
- */
-
- METHODDEF void
- c_ui_method_selection (compress_info_ptr cinfo)
- {
- /* If the input is gray scale, generate a monochrome JPEG file. */
- if (cinfo->in_color_space == CS_GRAYSCALE)
- j_monochrome_default(cinfo);
- /* For now, always select JFIF output format. */
- #ifdef JFIF_SUPPORTED
- jselwjfif(cinfo);
- #else
- You shoulda defined JFIF_SUPPORTED. /* deliberate syntax error */
- #endif
- }
-
-
- LOCAL void
- usage (char * progname)
- /* complain about bad command line */
- {
- fprintf(stderr, "usage: %s ", progname);
- fprintf(stderr, "[-I] [-Q quality 0..100] [-a] [-o] [-d]");
- #ifdef TWO_FILE_COMMANDLINE
- fprintf(stderr, " inputfile outputfile\n");
- #else
- fprintf(stderr, " [inputfile]\n");
- #endif
- exit(2);
- }
-
-
- /*
- * The main program.
- */
-
- GLOBAL void
- main (int argc, char **argv)
- {
- struct compress_info_struct cinfo;
- struct compress_methods_struct c_methods;
- struct external_methods_struct e_methods;
- int c;
-
- /* On Mac, fetch a command line. */
- #ifdef THINK_C
- argc = ccommand(&argv);
- #endif
-
- /* Initialize the system-dependent method pointers. */
- cinfo.methods = &c_methods;
- cinfo.emethods = &e_methods;
- jselerror(&e_methods); /* error/trace message routines */
- jselvirtmem(&e_methods); /* memory allocation routines */
- c_methods.c_ui_method_selection = c_ui_method_selection;
-
- /* Set up default input and output file references. */
- /* (These may be overridden below.) */
- cinfo.input_file = stdin;
- cinfo.output_file = stdout;
-
- /* Set up default parameters. */
- e_methods.trace_level = 0;
- j_default_compression(&cinfo, 75); /* default quality level */
-
- /* Scan parameters */
-
- while ((c = getopt(argc, argv, "IQ:aod")) != EOF)
- switch (c) {
- case 'I': /* Create noninterleaved file. */
- #ifdef MULTISCAN_FILES_SUPPORTED
- cinfo.interleave = FALSE;
- #else
- fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
- argv[0]);
- exit(2);
- #endif
- break;
- case 'Q': /* Quality factor. */
- { int val;
- if (optarg == NULL)
- usage(argv[0]);
- if (sscanf(optarg, "%d", &val) != 1)
- usage(argv[0]);
- /* Note: for now, we leave force_baseline FALSE.
- * In a production user interface, probably should make it TRUE
- * unless overridden by a separate switch.
- */
- j_set_quality(&cinfo, val, FALSE);
- }
- break;
- case 'a': /* Use arithmetic coding. */
- #ifdef ARITH_CODING_SUPPORTED
- cinfo.arith_code = TRUE;
- #else
- fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
- argv[0]);
- exit(2);
- #endif
- break;
- case 'o': /* Enable entropy parm optimization. */
- #ifdef ENTROPY_OPT_SUPPORTED
- cinfo.optimize_coding = TRUE;
- #else
- fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
- argv[0]);
- exit(2);
- #endif
- break;
- case 'd': /* Debugging. */
- e_methods.trace_level++;
- break;
- case '?':
- default:
- usage(argv[0]);
- break;
- }
-
- /* Select the input and output files */
-
- #ifdef TWO_FILE_COMMANDLINE
-
- if (optind != argc-2) {
- fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
- usage(argv[0]);
- }
- if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
- exit(2);
- }
- if ((cinfo.output_file = fopen(argv[optind+1], WRITE_BINARY)) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind+1]);
- exit(2);
- }
-
- #else /* not TWO_FILE_COMMANDLINE -- use Unix style */
-
- if (optind < argc-1) {
- fprintf(stderr, "%s: only one input file\n", argv[0]);
- usage(argv[0]);
- }
- if (optind < argc) {
- if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
- fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
- exit(2);
- }
- }
-
- #endif /* TWO_FILE_COMMANDLINE */
-
- /* Figure out the input file format, and set up to read it. */
- select_file_type(&cinfo);
-
- /* Do it to it! */
- jpeg_compress(&cinfo);
-
- /* Release memory. */
- j_free_defaults(&cinfo);
- #ifdef MEM_STATS
- if (e_methods.trace_level > 0)
- j_mem_stats();
- #endif
-
- /* All done. */
- exit(0);
- }
-